package lexer

// TokenType 表示token的类型
type TokenType int

const (
	TokenEOF            TokenType = iota //结束
	TokenHeading                         //标题
	TokenText                            //文本
	TokenList                            //列表
	TokenBold                            //粗体
	TokenCodeBlock                       //代码块
	TokenItalic                          //斜体
	TokenLink                            //链接
	TokenImage                           //图片
	TokenTable                           //表格
	TonenNewline                         //换行
	TokenHorizontalLine                  //水平线
)

// Token 表示一个词法单元
type Token struct {
	Type    TokenType
	Content string //内容
	Line    int    //行号
	Column  int    //列号
}

//Lexer 词法分析器
type Lexer struct {
	input   string
	ch      byte //当前字符
	pos     int  //当前位置
	readPos int  //已读位置
	length  int  //输入长度
	line    int  //当前行号
	column  int  //当前列号
}

// NewLexer 创建一个新的词法分析器
func NewLexer(input string) *Lexer {
	lexer := &Lexer{
		input:   input,
		pos:     0,
		readPos: 0,
		length:  len(input),
		line:    1,
		column:  1,
	}
	lexer.readChar()
	return lexer
}

// NextToken 获取下一个词法单元
func (l *Lexer) NextToken() Token {
	var tok Token
	l.skipWhitespace()
	switch l.ch {
	case '#':
		//标题
		// 识别标题
		tok = l.parseHeading()

	case '*':
		//*斜体
		if l.peekChar() == '*' {
			//两个*粗体
			l.readChar()
		}
		tok = l.parseHeading()

	case '_':
		//*斜体
		if l.peekChar() == '_' {
			//两个*粗体
			l.readChar()
		}
		// 识别标题
		tok = l.parseHeading()

	}
	l.readChar()
	return tok
}

func newToken(tokenType TokenType, content string, line, column int) Token {
	return Token{Type: tokenType, Content: content, Line: line, Column: column}
}

//读取字符
func (l *Lexer) readChar() {
	if l.readPos >= l.length {
		l.ch = 0
	} else {
		l.ch = l.input[l.readPos]
	}
	l.pos = l.readPos
	l.readPos += 1
}
func (l *Lexer) peekChar() byte {
	if l.readPos >= l.length {
		return 0
	} else {
		return l.input[l.readPos]
	}
}
func (l *Lexer) skipWhitespace() {
	for l.ch == ' ' || l.ch == '\t' || l.ch == '\n' || l.ch == '\r' {
		l.readChar()
	}
}
func (l *Lexer) parseHeading() Token {
	l.readChar()
	l.skipWhitespace()
	return newToken(TokenHeading, l.readHeading(), l.line, l.column)
}

func (l *Lexer) readHeading() string {
	startPos := l.pos
	l.pos = l.pos + 1
	for {
		l.readChar()
		if l.ch == ' ' || l.ch == '\t' || l.ch == '\n' || l.ch == '\r' || l.ch == 0 {
			break
		}
	}
	content := l.input[startPos:l.pos]
	return content
}
